package dao

import (
	"context"
	"fmt"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
	rentalpb "serve/rental/api/gen/v1"
	"serve/shared/id"
	mgutil "serve/shared/mongo"
)

/*
db.profile.createIndex({
accountid:1
},
{
unique:true
}
)
*/

type Mongo struct {
	col *mongo.Collection
}

const (
	accountIDField      = "accountid"
	profileField        = "profile"
	identityStatusField = profileField + ".identity_status"
	photoBlobIdField    = "photoblobid"
)

func NewMongo(db *mongo.Database) *Mongo {
	return &Mongo{col: db.Collection("profile")}
}

type ProfileRecord struct {
	AccountID   string            `json:"account_id,omitempty"`
	Profile     *rentalpb.Profile `json:"profile,omitempty"`
	PhotoBlobID string            `bson:"photoblobid"`
}

func (m *Mongo) GetProfile(c context.Context, aid id.AccountID) (*ProfileRecord, error) {
	res := m.col.FindOne(c, byAccountId(aid))

	if err := res.Err(); err != nil {
		return nil, err
	}

	var pr ProfileRecord
	err := res.Decode(&pr)
	if err != nil {
		return nil, fmt.Errorf("驾照信息查询失败")
	}

	return &pr, nil
}

func (m *Mongo) UpdateProfilePhoto(c context.Context, aid id.AccountID, bid id.BlobID) error {
	_, err := m.col.UpdateOne(c, bson.M{
		accountIDField: aid.String(),
	}, mgutil.Set(bson.M{
		accountIDField:   aid.String(),
		photoBlobIdField: bid,
	}), options.Update().SetUpsert(true))

	return err
}

func (m *Mongo) UpdateProfile(c context.Context, aid id.AccountID, prevState rentalpb.Identity_Status, p *rentalpb.Profile) error {
	filter := bson.M{
		identityStatusField: prevState,
	}

	if prevState == rentalpb.Identity_Status_PENDING {
		filter = mgutil.ZeroOrDoesNotExist(identityStatusField, prevState)
	}
	filter[accountIDField] = aid.String()

	_, err := m.col.UpdateOne(c, filter, mgutil.Set(bson.M{
		accountIDField: aid.String(),
		profileField:   p,
	}), options.Update().SetUpsert(true))

	return err
}

func byAccountId(aid id.AccountID) bson.M {
	return bson.M{
		accountIDField: aid.String(),
	}
}

func (m *Mongo) DeleteProfile(c context.Context, aid id.AccountID) error {
	_, err := m.col.DeleteOne(c, bson.M{
		accountIDField: aid.String(),
	})
	return err
}
